package com.tanjie.blackbean.schedule.support;

import com.tanjie.blackbean.schedule.properties.ScheduleConfigProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronExpression;
import org.springframework.scheduling.support.CronTrigger;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

import static com.tanjie.blackbean.schedule.support.ScheduleExecutionType.CRON;

/**
 * @Author tanjie
 * @Date 2022/6/23 下午4:18 周四
 **/
@Slf4j
@AllArgsConstructor
public class BlackbeanSchedule {

    ThreadPoolTaskScheduler scheduleThreadPoolTaskScheduler;

    ScheduleConfigProperties scheduleConfigProperties;

    ScheduledFutureHolder scheduledFutureHolder;

    public Map<String, ScheduledFuture<?>> getRunningSchedule(){
        return scheduledFutureHolder.all();
    }

    public List<ScheduleConfigProperties.ScheduleConfig> getScheduleConfigList() {
        return scheduleConfigProperties.getScheduleConfigList();
    }

    public void runOnStart() {
        Boolean runOnStart = scheduleConfigProperties.getRunOnStart();
        if (!runOnStart) {
            return;
        }
        List<ScheduleConfigProperties.ScheduleConfig> scheduleConfigs = scheduleConfigProperties.getScheduleConfigList();
        // 启动定时任务
        if (scheduleConfigs != null && scheduleConfigs.size() > 0) {
            for (ScheduleConfigProperties.ScheduleConfig config : scheduleConfigs) {
                if (!config.getRunOnStart()) {
                    continue;
                }
                String title = config.getTitle();
                String taskName = config.getTaskName();
                Boolean enable = config.getEnable();
                ScheduleExecutionType type = config.getType();
                String id = config.getId();
                long period = config.getPeriod();
                String cron = config.getCron();
                String futureKey = id + "-" + title + "-" + taskName + "-" + type;
                if (CRON.equals(type)) {
                    futureKey += "-[" + cron + "]";
                } else {
                    futureKey += "-" + period;
                }
                log.info("{} enable:{}", futureKey, enable);
                if (!enable) {
                    continue;
                }
                AbstractTask task = TaskHolder.get(taskName);
                if (task == null) {
                    log.warn("taskName:{} is undefined", taskName);
                    continue;
                }
                switch (type) {
                    case FIXED_RATE:
                        scheduledFutureHolder.add(futureKey, scheduleThreadPoolTaskScheduler.scheduleAtFixedRate(task, period));
                        break;
                    case FIXED_DELAY:
                        scheduledFutureHolder.add(futureKey, scheduleThreadPoolTaskScheduler.scheduleWithFixedDelay(task, period));
                        break;
                    case CRON:
                        if (!CronExpression.isValidExpression(cron)) {
                            log.warn("定时任务:{}是cron类型，但cron表达式[{}]无效", title, cron);
                        } else {
                            scheduledFutureHolder.add(futureKey, scheduleThreadPoolTaskScheduler.schedule(task, new CronTrigger(cron)));
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }

}
